package org.common.util;

import org.common.constant.GlobalConfig;

import java.sql.*;
import java.util.Objects;
import java.util.Properties;

/**
 * JDBC连接和释放资源工具类。
 * TIPS: 未使用连接池
 *
 * @author yexi
 */
public final class JDBCUtil {
    private JDBCUtil() {
    }

    private static final Properties PROPERTIES = new Properties();

    /*
     * 调用工具类时就自动加载驱动
     */
    static {
        try {
            //读取配置文件
            PROPERTIES.load(Objects.requireNonNull(Thread.currentThread().getContextClassLoader().getResourceAsStream(GlobalConfig.RESOURCE_NAME)));
            String active = PROPERTIES.getProperty("active");
            //加载驱动(因为只加载一次,所以放static即可)
            Class.forName(PROPERTIES.getProperty(GlobalConfig.getDriver(active)));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 返回加载的配置文件资源(提供给其他模块使用)
     */
    public static Properties getProperties() {
        return PROPERTIES;
    }

    /**
     * 返回加载的配置文件资源(提供给连接池模块使用)
     */
    public static Properties getPropertiesConnPool() {
        return getPropertiesConnPool(false);
    }

    /**
     * 返回加载的配置文件资源(提供给连接池模块使用)
     */
    public static Properties getPropertiesConnPool(boolean isHikari) {
        Properties properties = new Properties();
        String active = PROPERTIES.getProperty("active");
        properties.setProperty(GlobalConfig.DRIVER, PROPERTIES.getProperty(GlobalConfig.getDriver(active)));
        properties.setProperty(isHikari ? GlobalConfig.JDBC_URL : GlobalConfig.URL, PROPERTIES.getProperty(GlobalConfig.getUrl(active)));
        properties.setProperty(GlobalConfig.USERNAME, PROPERTIES.getProperty(GlobalConfig.getUsername(active)));
        properties.setProperty(GlobalConfig.PASSWORD, PROPERTIES.getProperty(GlobalConfig.getPassword(active)));
        return properties;
    }

    /**
     * 获取链接对象
     */
    public static Connection getConnection() {
        //获取链接对象
        Connection connection = null;
        try {
            String active = PROPERTIES.getProperty("active");
            connection = DriverManager.getConnection(
                    PROPERTIES.getProperty(GlobalConfig.getUrl(active)),
                    PROPERTIES.getProperty(GlobalConfig.getUsername(active)),
                    PROPERTIES.getProperty(GlobalConfig.getPassword(active)));
        } catch (SQLException e) {
            if ("com.microsoft.sqlserver.jdbc.SQLServerException".equals(e.getClass().getName())) {
                if (e.getMessage().contains("SSL")) {
                    throw new RuntimeException("获取数据库连接失败，原因是连接SQLServer的SSL验证不通过，可能原因是SQLServer服务器使用较旧的SSL算法，" +
                            "而你使用的jdk版本较新，因此安全校验时舍弃了不安全的旧算法所致。若非不可抗力，则建议更新SQLServer服务器使用的SSL算法，" +
                            "否则通过修改jdk中的java.security中的jdk.tls.disabledAlgorithms从而让jdk校验时不会对旧算法进行抛错", e);
                }
            }
            throw new RuntimeException("获取数据库连接失败", e);
        }
        return connection;
    }

    /**
     * 释放资源
     *
     * @param resultSet  表示数据库结果集的数据表
     * @param statement  语句对象
     * @param connection 链接对象
     */
    public static void release(ResultSet resultSet, Statement statement, Connection connection) {
        //释放资源
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    public static void release(Statement statement, Connection connection) {
        release(null, statement, connection);
    }

}
